package com.ums.upos.service;

import android.os.RemoteException;
import android.text.TextUtils;

import com.nexgo.common.ByteUtils;
import com.nexgo.oaf.apiv3.SdkResult;
import com.nexgo.oaf.apiv3.device.serialport.SerialCfgEntity;
import com.ums.upos.GlobalDataHolder;
import com.ums.upos.uapi.ServiceResult;
import com.ums.upos.uapi.device.serialport.SerialPortDriver;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Created by xiaox on 15-10-7.
 */
public class SerialPortBinder extends SerialPortDriver.Stub {
    int portNo;
    private final String TAG = "SerialPort";
    private boolean isPortOpen = false;
    private Logger log;
    private com.nexgo.oaf.apiv3.device.serialport.SerialPortDriver sdkSerialPortDriver;

    //强制串口为0
    SerialPortBinder(int portNo) {
        log = LoggerFactory.getLogger(TAG);
        if (portNo == 1) {
            this.portNo = 0;
        } else {
            this.portNo = portNo;
        }
        sdkSerialPortDriver = GlobalDataHolder.getInstance().getDeviceEngine().getSerialPortDriver(0);

        log.info("structure--："+isPortOpen);
    }

    @Override
    public int connect(String cfg) throws RemoteException {
        log.info("call connect cfg {}", cfg);
        try {
            if (TextUtils.isEmpty(cfg)) return ServiceResult.Param_In_Invalid;
            String[] str = cfg.split(",");

            if (str.length != 4) return ServiceResult.Param_In_Invalid;

            int baud = Integer.valueOf(str[0]);
            String parity = str[1].toLowerCase();
            int dataBits = Integer.valueOf(str[2]);
            int stopBits = Integer.valueOf(str[3]);
            if (baud != 110 && baud != 300 && baud != 600 && baud != 1200 && baud != 2400 && baud != 4800 && baud != 9600 && baud != 14400
                    && baud != 56000 && baud != 19200 && baud != 38400 && baud != 57600 && baud != 115200 && baud != 230400)
                // FIXME: 2016/8/10 zhanghuan 按照测试案例文档修改方法返回值
                // return ServiceResult.SerialPort_Invalid_Channel;
                return ServiceResult.SerialPort_Invalid_Communication_Parameter;
            if (!parity.equals("o") && !parity.equals("e") && !parity.equals("n"))
                // return ServiceResult.SerialPort_Invalid_Channel;
                return ServiceResult.SerialPort_Invalid_Communication_Parameter;
            if (dataBits != 5 && dataBits != 6 && dataBits != 7 && dataBits != 8)
                // return ServiceResult.SerialPort_Invalid_Channel;
                return ServiceResult.SerialPort_Invalid_Communication_Parameter;
            if (stopBits != 1 && stopBits != 2)
                // return ServiceResult.SerialPort_Invalid_Channel;
                return ServiceResult.SerialPort_Invalid_Communication_Parameter;

            SerialCfgEntity serialCfgEntity = new SerialCfgEntity();
            serialCfgEntity.setBaudRate(baud);
            serialCfgEntity.setParity(parity.charAt(0));
            serialCfgEntity.setDataBits(dataBits);
            serialCfgEntity.setStopBits(stopBits);
            int result = sdkSerialPortDriver.connect(serialCfgEntity);
            log.debug("connect portNo {},{}", portNo, result);
            if (result == SdkResult.Success) {
                isPortOpen = true;
                log.info("串口连接成功--："+isPortOpen);
                return ServiceResult.Success;
            } else {
                return ServiceResult.SerialPort_Connect_Fail;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return ServiceResult.Fail;
        }
    }

    @Override
    public int send(byte[] data, int dataLen) throws RemoteException {
        log.info("call send");
        try {
            // FIXME: 2016/8/10 zhanghuan  增加dataLen小于0的判断
            if (data == null || data.length == 0 || data.length < dataLen || dataLen < 0)
                return ServiceResult.Param_In_Invalid;

            if (!isPortOpen) return ServiceResult.SerialPort_Port_Not_Open;

            if (data.length > dataLen) {
                byte[] tmp = new byte[dataLen];
                System.arraycopy(data, 0, tmp, 0, dataLen);
                data = tmp;
            }
            log.debug("send data {}", ByteUtils.byteArray2HexString(data));
            int result = sdkSerialPortDriver.send(data, dataLen);
            log.debug("send {}", result);
            if (result == SdkResult.Success) {
                return ServiceResult.Success;
            } else {
                return ServiceResult.SerialPort_Send_Fail;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return ServiceResult.Fail;
        }
    }

    @Override
    public int recv(byte[] buffer, int recvLen, final long timeout) throws RemoteException {
        log.info("call recv");
        try {
            if (buffer == null || buffer.length == 0 || recvLen <= 0 || timeout < 0 )
                return ServiceResult.Param_In_Invalid;

            if (!isPortOpen) return ServiceResult.SerialPort_Port_Not_Open;

            if(recvLen > buffer.length){
                recvLen = buffer.length;
            }
            //result 为接收数据的长度
            int result = sdkSerialPortDriver.recv(buffer, recvLen, timeout);
            if (result >= 0) {
                return recvLen;

            }else if (result == SdkResult.SerialPort_Timeout_Receiving_Data) {
                return ServiceResult.SerialPort_Timeout_Receiving_Data;
            } else {
                return ServiceResult.Fail;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return ServiceResult.Fail;
        }
    }

    @Override
    public int disconnect() throws RemoteException {
        log.info("call disconnect");
        // FIXME: 2016/8/11 zhanghuan 断开串口时候，判断串口是否打开
        if (!isPortOpen) return ServiceResult.SerialPort_Port_Not_Open;
        int result = sdkSerialPortDriver.disconnect();
        if (result == SdkResult.Success) {
            isPortOpen = false;
            return ServiceResult.Success;
        } else {
            return ServiceResult.SerialPort_DisConnect_Fail;
        }
    }

    @Override
    public void clrBuffer() throws RemoteException {
        log.info("call clrBuffer");
        try {
            sdkSerialPortDriver.clrBuffer();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
